JDBC简介
概念
Java DataBase Connectivity,Java 数据库连接。
JDBC是sun公司定义的一套操作所有关系型数据库的规则,即接口。
各个数据库厂商去编写这套接口的实现类,包装成数据库驱动jar包。通过导入不同数据库厂商编写的数据库驱动jar包,来对JBDC接口进行实现。
快速入门
- 导入MySQL数据库驱动jar包
- mysql-connector-java-5.1.37-bin.jar
- 复制到项目的libs目录下
- 右键 –> Add As Library
- 注册驱动 driver
- “com.mysql.jdbc.Driver”
- 获取数据库连接对象 Connection
- 第一个参数:URL(jdbc:mysql://连接IP地址:端口号/数据库名)
- 第二个参数:数据库账号
- 第三个参数:数据库密码
- 定义SQL语句
- 获取执行SQL语句的对象 Statement
- 执行SQL语句,接受返回结果
- 处理结果
- 释放资源
1 | # 创建数据库 |
1 | //1.导入驱动jar包 |
详解对象
DriverManager
- DriverManager驱动管理对象:用于管理一组JDBC驱动程序的基本服务。
- 新增的DataSource接口提供了另一种连接到数据源的方法。 使用DataSource对象是连接到数据源的首选方法。
注册驱动
- 注册驱动:其实就是一个指定数据库驱动jar包的过程。
- 我们在快速入门的时候,使用的注册驱动方式是加载文件:
- 加载MySQL数据库驱动jar包中的com.mysql.jdbc.Driver类
- Class.forName(“com.mysql.jdbc.Driver”);
- 加载MySQL数据库驱动jar包中的com.mysql.jdbc.Driver类
- 那么为什么加载com.mysql.jdbc.Driver类就能够注册驱动呢?我们来探究一下。
- 其实真正注册驱动调用的是DriverManager类中的registerDriver静态方法
- 注册与给定的驱动程序 DriverManager :static void registerDriver(Driver driver)
- 而由于com.mysql.jdbc.Driver类在其静态代码块调用了registerDriver静态方法,所以当我们去加载这个类时,它会帮我们自动的注册驱动,简便了我们的操作。
- 其实真正注册驱动调用的是DriverManager类中的registerDriver静态方法
- MySQL5之后的驱动jar包可以省略注册驱动的步骤,因为它自动加载了com.mysql.jdbc.Driver类。
1
2
3
4
5
6
7
8/* com.mysql.jdbc.Driver类中的静态代码块 */
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
获取数据库连接
- static Connection getConnection(String url, String user, String password)
- Connection数据库连接对象:与特定数据库的连接。
获取执行SQL语句的对象
- Statement createStatement() :创建一个 Statement对象,用于将SQL语句发送到数据库。
- PreparedStatement prepareStatement(String sql) :创建一个 PreparedStatement对象,用于将参数化的SQL语句发送到数据库。
管理事务
- void setAutoCommit(boolean autoCommit) :(开启事务)将此连接的自动提交模式设置为给定状态。
- true(自动提交)
- false(手动提交,开启事务)
- void commit() :(提交事务)使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection对象当前持有的任何数据库锁。
- void rollback() :(回滚事务)撤消在当前事务中所做的所有更改,并释放此 Connection对象当前持有的任何数据库锁。
Statement
- Statement执行静态SQL语句的对象:用于执行静态SQL语句并返回其生成的结果的对象。
执行sql
- boolean execute(String sql) :可以执行任意的SQL语句
- int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
- 返回值:影响的行数
- 通过影响的行数可以判断语句是否执行成功。返回值>0的则执行成功,反之,则失败。
- ResultSet executeQuery(String sql) :执行DQL(select)语句
练习:增删改
添加记录
注意:添加记录调用的是executeUpdate方法
1 | public static void main(String[] args) { |
修改记录
除了SQL语句,所有的代码都跟添加记录的练习一模一样。
注意:修改记录执行SQL语句的是executeUpdate方法
1 | // ..... |
删除记录
除了SQL语句,所有的代码都跟添加记录的练习一模一样。
注意:删除记录执行SQL语句的是executeUpdate方法
1 | // ..... |
ResultSet
- ResultSet结果集对象:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
封装查询结果
- boolean next()::游标向下移动一行,并判断当前行是否是最后一行的末尾(是否有数据)。
- 如果是最后一行的末尾,则返回false;如果不是,则返回true。
- getTYPE(参数):获取数据
- TYPE:代表数据类型
- 如: int getInt() ,String getString()
- 参数:
- int:代表列的编号,从1开始
- 如: getString(1)
- String:代表列名称。
- 如: getDouble(“balance”)
- int:代表列的编号,从1开始
- TYPE:代表数据类型
- 使用步骤:
- 游标向下移动一行
- 判断是否有数据
- 获取数据
练习:查询
查询记录
除了SQL语句、执行SQL语句和处理结果不一样,所有的代码都跟添加记录的练习一模一样。另外,你要在trycatch语句外声明一个ResultSet对象为NULL,并在finally语句中释放ResultSet资源。
注意:查询记录执行SQL语句的是executeQuery方法
1 | // ..... |
查询记录(实体类)
代码
- 查询数据库中emp表的数据,并将其封装为Employee对象,然后将其封装进List集合。
1 | # MySQL数据库 |
1 | // 实体类 |
1 | // 测试类 |
比较
将数据库、实体类和测试类进行比较。
1 | # MySQL数据库 |
1 | // 实体类 |
1 | // 测试类 |
PreparedStatement
- PreparedStatement执行动态SQL语句的对象:表示预编译(动态)的SQL语句的对象。
SQL注入问题
- 指在拼接SQL时,有一些特殊的SQL关键字参与,从而造成了安全性问题。
用户输入前
1 | // Java语句 |
用户输入后, 账户:随便,密码:a’ or ‘a’=’a
1 | # SQL语句 |
解决SQL注入问题
- 使用PreparedStatement对象来解决SQL注入问题。
- 预编译(动态)的SQL:参数使用?作为占位符
- 使用步骤:
- 导入驱动jar包
- 注册驱动
- 获取数据库连接对象 Connection
- 定义sql
- 注意:sql的参数使用?作为占位符。
- 如:select * from user where username = ? and password = ?;
- 传递SQL语句,获取执行动态SQL语句的对象 PreparedStatement
- 给?占位符赋值:
- 方法: setXxx(参数1,参数2)
- 参数1:?占位符的位置编号,从1 开始
- 参数2:?占位符的值
- 方法: setXxx(参数1,参数2)
- 执行sql,接受返回结果,不需要传递sql语句
- 处理结果
- 释放资源
登录案例
- 需求
- 用户通过键盘录入用户名和密码;
- 查询数据库后,判断用户是否登录成功。
使用静态SQL
1 | # 创建表 |
1 | // [main方法] |
使用动态SQL
1 | // ..... |
JDBC工具类
- 经过几个JDBC的案例之后,我们不难发现JDBC的编写中存在大量复杂的相同的代码,为了简化书写,我们引入了JDBC工具类:JDBCUtils。
- 但仅仅使用JDBC工具类,仍然不能使得获取数据库连接对象的代码变得简洁,而我们每次在获取数据库连接对象时,输入的三个参数是很少会变化的。于是,为了更加简化书写,我们引入了JDBC配置文件:jdbc.properties。
- 为了达到最终的目的,我们需要在JDBC工具类中来编写以下内容:
- 静态变量
- 静态代码块
- 获取数据库连接对象的静态方法
- 增删改操作释放资源的静态方法
- 查询操作释放资源的静态方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85//J DBC工具类:JDBCUtils
public class JDBCUtils {
// [静态变量]
private static String url;
private static String user;
private static String password;
private static String driver;
// [静态代码块:读取配置文件的数据]
static {
try {
// 1.创建properties对象
Properties properties = new Properties();
// 1.1 获取 字节码文件
Class jdbcClass = JDBCUtils.class;
// 1.2 获取 类加载器
ClassLoader classLoader = jdbcClass.getClassLoader();
// 1.3 获取 统一资源定位符
URL resource = classLoader.getResource("jdbc.properties");
// 1.4 获取 路径
String path = resource.getPath();
// 2.加载配置文件
properties.load(new FileReader(path));
// 3.获取数据
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
driver = properties.getProperty("driver");
// 4.注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//[成员方法:获取Connection对象]
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
//[成员方法:增删改操作释放Connection对象、Statement对象]
public static void close(Statement stat, Connection conn) {
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//[成员方法:查询操作释放Connection对象、Statement对象、ResultSet对象]
public static void close(Statement stat, Connection conn, ResultSet reSet) {
if (reSet != null) {
try {
reSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
1 | # properties提示配置文件 |
查询练习
1 | // 使用JDBC工具类 |
JDBC控制事务
事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
JDBC使用Connection对象来管理事务
开启事务:setAutoCommit(boolean autoCommit) (false为开启事务)
- 在执行sql之前开启事务
提交事务:commit()
- 当所有sql都执行完提交事务
回滚事务:rollback()
- 在catch中回滚事务
- 我在代码中写入了一句异常 ,当程序运行到异常时,异常后的提交事务不会进行,程序运行catch语句,进行事务回滚,账户会回滚到之前的状态。当然,如果去除异常,交易会正常进行,账户会发生变化。
1 | public static void main(String[] args) { |